﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Formatting;
using Newtonsoft.Json.Serialization;
using Sustainalytics.ESGRatings.Computing.Entities;
using Sustainalytics.ESGRatings.Computing.Entities.ESG;
using Sustainalytics.ESGRatings.DataContract;


namespace Sustainalytics.ESGComputing.Service.Tests
{
    public class RankingDataFixture : Disposable
    {
        private const string SutLink = "http://localhost:10280/esgcomputingserv/api/v1";

        private static readonly JsonMediaTypeFormatter JsonMediaTypeFormatter = new JsonMediaTypeFormatter
        {
            SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
        };

        private static HttpClient _sutClient = new HttpClient();

        private bool _disposed;

        public RankingDataFixture()
        {
            var data = GetData();
            Matrices = data.Matrices;
            ReferenceUniverses = data.ReferenceUniverses;
            Companies = data.Companies;
            IndicatorTemplates = data.IndicatorTemplates;
            CompanyScores = data.CompaniesScores;

            _sutClient.PostAsync($"{SutLink}/dataprovisioning/esgsets", data, JsonMediaTypeFormatter).Result.EnsureSuccessStatusCode();
        }

        ~RankingDataFixture()
        {
            Dispose(false);
        }

        public CompanyData[] Companies { get; private set; }

        public CompanyScores[] CompanyScores { get; private set; }

        public IndicatorTemplate[] IndicatorTemplates { get; private set; }

        public WeightMatrix[] Matrices { get; private set; }
        public ReferenceUniverse[] ReferenceUniverses { get; set; }
        protected override void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    var taskClean = _sutClient.PostAsync(string.Format("{0}{1}", SutLink, "/health/clean"), string.Empty,
                        JsonMediaTypeFormatter);
                    taskClean.Result.EnsureSuccessStatusCode();
                    _sutClient.Dispose();
                    _sutClient = null;
                }
                _disposed = true;
            }
            base.Dispose(disposing);
        }

        private CompanyData[] GetCorporateData(IList<Guid> companyIds)
        {
            var companies = new[]
            {
                new CompanyData { Id = companyIds[0], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[1], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[2], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[3], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[4], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[5], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Diversified Financials", PeerGroup = "Diversified Financials" },
                new CompanyData { Id = companyIds[6], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Banks",                  PeerGroup = "Banks" },
                new CompanyData { Id = companyIds[7], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Banks",                  PeerGroup = "Banks" },
                new CompanyData { Id = companyIds[8], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Banks",                  PeerGroup = "Banks" },
                new CompanyData { Id = companyIds[9], CompanyType = "Public",   TemplateType = "Type A", IndustryGroup = "Banks",                  PeerGroup = "Banks" }
            };
            return companies;
        }

        private ESGDataContainer GetData()
        {
            Guid matrixId1 = new Guid("00000000-0000-0000-0000-000000000001");
            Guid referenceUniversesId1 = new Guid("00000000-0000-0000-0000-000000000002");
            Guid referenceUniversesId2 = new Guid("00000000-0000-0000-0000-000000000003");

            IList<Guid> companyIds = new List<Guid>
        {
            new Guid("00000000-0000-0000-0000-000000000001"),
            new Guid("00000000-0000-0000-0000-000000000002"),
            new Guid("00000000-0000-0000-0000-000000000003"),
            new Guid("00000000-0000-0000-0000-000000000004"),
            new Guid("00000000-0000-0000-0000-000000000005"),
            new Guid("00000000-0000-0000-0000-000000000006"),
            new Guid("00000000-0000-0000-0000-000000000007"),
            new Guid("00000000-0000-0000-0000-000000000008"),
            new Guid("00000000-0000-0000-0000-000000000009"),
            new Guid("00000000-0000-0000-0000-000000000010"),
        };

            var data = new ESGDataContainer();
            data.Companies = GetCorporateData(companyIds);
            data.IndicatorTemplates = GetIndicatorConfiguration();
            data.CompaniesScores = GetIndicatorsData(companyIds);
            data.ReferenceUniverses = new[]
            {
                GetFirstReferenceUniverse(referenceUniversesId1, companyIds),
                GetSecondReferenceUniverse(referenceUniversesId2,companyIds)
            };
            data.Matrices = new[]
            {
                new WeightMatrix()
                {
                    MatrixId = matrixId1,
                    CompaniesWeights = GetFirstMatrixCompanyWeightsData(companyIds)
                },
            };

            return data;
        }
        private CompanyWeights[] GetFirstMatrixCompanyWeightsData(IList<Guid> companyIds)
        {
            return new[]
            {
                new CompanyWeights  ( companyIds[0],
                    new[]
                    {
                        new Weight( "E.1.1",    0.1f    ),
                        new Weight( "E.1.2",    0       ),
                        new Weight( "E.1.12",   0.15f   ),
                        new Weight( "E.2.2",    0       ),
                        new Weight( "E.1.4",    0       ),
                        new Weight( "G.1.4",    0       ),
                        new Weight( "G.1.1",    0.2f    ),
                        new Weight( "S.1.1",    0.25f   ),
                        new Weight( "S.1.2",    0.3f    )
                    }),
                new CompanyWeights  ( companyIds[1],
                    new[]
                    {
                        new Weight( "E.1.1",    0.15f  ),
                        new Weight( "E.1.2",    0.15f  ),
                        new Weight( "E.1.12",   0.05f  ),
                        new Weight( "E.2.2",    0.05f  ),
                        new Weight( "E.1.4",    0.03f  ),
                        new Weight( "G.1.4",    0.06f  ),
                        new Weight( "G.1.1",    0.04f  ),
                        new Weight( "S.1.1",    0.01f  ),
                        new Weight( "S.1.2",    0.01f  )
                    } ),
                new CompanyWeights  ( companyIds[2],
                    new[]
                    {
                        new Weight( "E.1.1", 0f),
                        new Weight( "E.1.2", 0.05f),
                        new Weight( "E.1.12", 0.1f),
                        new Weight( "E.2.2", 0f),
                        new Weight( "E.1.4", 0.0f),
                        new Weight( "G.1.4", 0.1f),
                        new Weight( "G.1.1", 0.2f),
                        new Weight( "S.1.1", 0.25f),
                        new Weight( "S.1.2", 0.3f)
                    } ),
                new CompanyWeights(companyIds[3],
                    new[]
                    {
                        new Weight("E.1.1",     0.1f    ),
                        new Weight("E.1.2",     0.15f   ),
                        new Weight("E.1.12",    0f      ),
                        new Weight("E.2.2",     0.2f    ),
                        new Weight("E.1.4",     0f      ),
                        new Weight("G.1.4",     0.2f    ),
                        new Weight("G.1.1",     0f      ),
                        new Weight("S.1.1",     0.35f   ),
                        new Weight("S.1.2",     0f      )
                    }),
              new CompanyWeights(companyIds[4],
                    new[]
                    {
                        new Weight("E.1.1",   0.2f      ),
                        new Weight("E.1.2",   0.3f      ),
                        new Weight("E.1.12",  0         ),
                        new Weight("E.2.2",   0         ),
                        new Weight("E.1.4",   0         ),
                        new Weight("G.1.4",   0.25f     ),
                        new Weight("G.1.1",   0         ),
                        new Weight("S.1.1",   0         ),
                        new Weight("S.1.2",   0.25f     )
                    }),

            new CompanyWeights(companyIds[5],
                    new[]
                    {
                        new Weight("E.1.1",   0f        ),
                        new Weight("E.1.2",   0.2f      ),
                        new Weight("E.1.12",  0.2f      ),
                        new Weight("E.2.2",   0f        ),
                        new Weight("E.1.4",   0.1f      ),
                        new Weight("G.1.4",   0f        ),
                        new Weight("G.1.1",   0.15f     ),
                        new Weight("S.1.1",   0.35f     ),
                        new Weight("S.1.2",   0f        )
                    }),
new CompanyWeights(companyIds[6],
                    new[]
                    {
                        new Weight("E.1.1",   0f        ),
                        new Weight("E.1.2",   0f        ),
                        new Weight("E.1.12",  0.3f      ),
                        new Weight("E.2.2",   0f        ),
                        new Weight("E.1.4",   0f        ),
                        new Weight("G.1.4",   0.25f     ),
                        new Weight("G.1.1",   0.25f     ),
                        new Weight("S.1.1",   0f        ),
                        new Weight("S.1.2",   0.2f      )
                    }),
new CompanyWeights(companyIds[7],
                    new[]
                    {
                        new Weight("E.1.1",   0.1f      ),
                        new Weight("E.1.2",   0.1f      ),
                        new Weight("E.1.12",  0f        ),
                        new Weight("E.2.2",   0f        ),
                        new Weight("E.1.4",   0.1f      ),
                        new Weight("G.1.4",   0.25f     ),
                        new Weight("G.1.1",   0.25f     ),
                        new Weight("S.1.1",   0.1f      ),
                        new Weight("S.1.2",   0.1f      )
                    }),
new CompanyWeights(companyIds[8],
                    new[]
                    {
                        new Weight("E.1.1",   0f        ),
                        new Weight("E.1.2",   0f        ),
                        new Weight("E.1.12",  0f        ),
                        new Weight("E.2.2",   0.15f     ),
                        new Weight("E.1.4",   0.15f     ),
                        new Weight("G.1.4",   0.3f      ),
                        new Weight("G.1.1",   0.3f      ),
                        new Weight("S.1.1",   0.1f      ),
                        new Weight("S.1.2",   0f        )
                    }),
new CompanyWeights(companyIds[9],
                    new[]
                    {
                        new Weight("E.1.1",   0f        ),
                        new Weight("E.1.2",   0f        ),
                        new Weight("E.1.12",  0f        ),
                        new Weight("E.2.2",   0.22f     ),
                        new Weight("E.1.4",   0.22f     ),
                        new Weight("G.1.4",   0.2f      ),
                        new Weight("G.1.1",   0.23f     ),
                        new Weight("S.1.1",   0.05f     ),
                        new Weight("S.1.2",   0.08f     )
                    }),
            };
        }

        private ReferenceUniverse GetFirstReferenceUniverse(Guid referenceUniverseId, IList<Guid> companyIds)
        {
            return
                   new ReferenceUniverse
                   {
                       Id = referenceUniverseId,
                       Companies = new[]
                    {
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704112",  CompanyId = companyIds[0], CompanyName = "Compania1" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704113",  CompanyId = companyIds[1], CompanyName = "Compania2" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704114",  CompanyId = companyIds[2], CompanyName = "Compania3" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704115",  CompanyId = companyIds[3], CompanyName = "Compania4" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704116",  CompanyId = companyIds[4], CompanyName = "Compania5" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704117",  CompanyId = companyIds[5], CompanyName = "Compania6" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704118",  CompanyId = companyIds[6], CompanyName = "Compania7" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704119",  CompanyId = companyIds[7], CompanyName = "Compania8" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ207041110", CompanyId = companyIds[8], CompanyName = "Compania9" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ207041111", CompanyId = companyIds[9], CompanyName = "Compania10" },
                    }
                   };
        }

        private IndicatorTemplate[] GetIndicatorConfiguration()
        {
            IndicatorTemplate[] builder =
            {
                new IndicatorTemplate("E.1.1",  "E", "P​​"),
                new IndicatorTemplate("E.1.2",  "E", "P​​"),
                new IndicatorTemplate("E.1.12", "E", "QLP"),
                new IndicatorTemplate("E.2.2",  "E", "QLP"),
                new IndicatorTemplate("E.1.4",  "E", "QNP"),
                new IndicatorTemplate("G.1.4",  "G", "D"),
                new IndicatorTemplate("G.1.1",  "G", "P​​"),
                new IndicatorTemplate("S.1.1",  "S", "P​​"),
                new IndicatorTemplate("S.1.2",  "S", "QLP")
            };
            return builder;
        }

        private CompanyScores[] GetIndicatorsData(IList<Guid> companyIds)
        {
            return new[]
            {
                new CompanyScores(companyIds[0], new[] { new IndicatorDefaultScore("E.1.1",100,0f,0f),    new IndicatorDefaultScore("E.1.2",0,0f,0f),  new IndicatorDefaultScore("E.1.12",55,0f,0f),  new IndicatorDefaultScore("E.2.2",20,0f,0f),  new IndicatorDefaultScore("E.1.4",0,0f,0f),   new IndicatorDefaultScore("G.1.4",90,0f,0f),      new IndicatorDefaultScore("G.1.1",50,0f,0f),  new IndicatorDefaultScore("S.1.1",20,0f,0f),  new IndicatorDefaultScore("S.1.2",30,0f,0f) }) ,
                new CompanyScores(companyIds[1], new[] { new IndicatorDefaultScore("E.1.1",50,0f,0f),     new IndicatorDefaultScore("E.1.2",99,0f,0f), new IndicatorDefaultScore("E.1.12",50,0f,0f),  new IndicatorDefaultScore("E.2.2",75,0f,0f),  new IndicatorDefaultScore("E.1.4",75,0f,0f),  new IndicatorDefaultScore("G.1.4",50,0f,0f),      new IndicatorDefaultScore("G.1.1",75,0f,0f),  new IndicatorDefaultScore("S.1.1",25,0f,0f),  new IndicatorDefaultScore("S.1.2",75,0f,0f) }) ,
                new CompanyScores(companyIds[2], new[] { new IndicatorDefaultScore("E.1.1",50,0f,0f),     new IndicatorDefaultScore("E.1.2",40,0f,0f), new IndicatorDefaultScore("E.1.12",100,0f,0f), new IndicatorDefaultScore("E.2.2",100,0f,0f),  new IndicatorDefaultScore("E.1.4",0,0f,0f),   new IndicatorDefaultScore("G.1.4",80,0f,0f),      new IndicatorDefaultScore("G.1.1",50,0f,0f),  new IndicatorDefaultScore("S.1.1",20,0f,0f),  new IndicatorDefaultScore("S.1.2",30,0f,0f) }),
                new CompanyScores(companyIds[3], new[] { new IndicatorDefaultScore("E.1.1",0,0f,0f),      new IndicatorDefaultScore("E.1.2",10,0f,0f), new IndicatorDefaultScore("E.1.12",100,0f,0f), new IndicatorDefaultScore("E.2.2",25,0f,0f),  new IndicatorDefaultScore("E.1.4",0,0f,0f),   new IndicatorDefaultScore("G.1.4",0,0f,0f),       new IndicatorDefaultScore("G.1.1",25,0f,0f),  new IndicatorDefaultScore("S.1.1",75,0f,0f),  new IndicatorDefaultScore("S.1.2",30,0f,0f) }) ,
                new CompanyScores(companyIds[4], new[] { new IndicatorDefaultScore("E.1.1",25,0f,0f),     new IndicatorDefaultScore("E.1.2",25,0f,0f), new IndicatorDefaultScore("E.1.12",25,0f,0f),  new IndicatorDefaultScore("E.2.2",25,0f,0f),  new IndicatorDefaultScore("E.1.4",35,0f,0f),  new IndicatorDefaultScore("G.1.4",35,0f,0f),      new IndicatorDefaultScore("G.1.1",25,0f,0f),  new IndicatorDefaultScore("S.1.1",99,0f,0f),  new IndicatorDefaultScore("S.1.2",0,0f,0f) }) ,
                new CompanyScores(companyIds[5], new[] { new IndicatorDefaultScore("E.1.1",0,0f,0f),      new IndicatorDefaultScore("E.1.2",0,0f,0f),  new IndicatorDefaultScore("E.1.12",30,0f,0f),  new IndicatorDefaultScore("E.2.2",30,0f,0f),  new IndicatorDefaultScore("E.1.4",25,0f,0f),  new IndicatorDefaultScore("G.1.4",10,0f,0f),      new IndicatorDefaultScore("G.1.1",10,0f,0f),  new IndicatorDefaultScore("S.1.1",100,0f,0f), new IndicatorDefaultScore("S.1.2",0,0f,0f) }),
                new CompanyScores(companyIds[6], new[] { new IndicatorDefaultScore("E.1.1",100,0f,0f),    new IndicatorDefaultScore("E.1.2",100,0f,0f),new IndicatorDefaultScore("E.1.12",85,0f,0f),  new IndicatorDefaultScore("E.2.2",85,0f,0f),  new IndicatorDefaultScore("E.1.4",99,0f,0f),  new IndicatorDefaultScore("G.1.4",0,0f,0f),       new IndicatorDefaultScore("G.1.1",0,0f,0f),   new IndicatorDefaultScore("S.1.1",100,0f,0f), new IndicatorDefaultScore("S.1.2",100,0f,0f) }) ,
                new CompanyScores(companyIds[7], new[] { new IndicatorDefaultScore("E.1.1",25,0f,0f),     new IndicatorDefaultScore("E.1.2",25,0f,0f), new IndicatorDefaultScore("E.1.12",25,0f,0f),  new IndicatorDefaultScore("E.2.2",25,0f,0f),  new IndicatorDefaultScore("E.1.4",25,0f,0f),  new IndicatorDefaultScore("G.1.4",10,0f,0f),      new IndicatorDefaultScore("G.1.1",10,0f,0f),  new IndicatorDefaultScore("S.1.1",100,0f,0f), new IndicatorDefaultScore("S.1.2",100,0f,0f) }) ,
                new CompanyScores(companyIds[8], new[] { new IndicatorDefaultScore("E.1.1",0,0f,0f),      new IndicatorDefaultScore("E.1.2",0,0f,0f),  new IndicatorDefaultScore("E.1.12",30,0f,0f),  new IndicatorDefaultScore("E.2.2",30,0f,0f),  new IndicatorDefaultScore("E.1.4",0,0f,0f),   new IndicatorDefaultScore("G.1.4",100,0f,0f),     new IndicatorDefaultScore("G.1.1",100,0f,0f), new IndicatorDefaultScore("S.1.1",100,0f,0f),  new IndicatorDefaultScore("S.1.2",80,0f,0f) }),
                new CompanyScores(companyIds[9], new[] { new IndicatorDefaultScore("E.1.1",10,0f,0f),     new IndicatorDefaultScore("E.1.2",10,0f,0f), new IndicatorDefaultScore("E.1.12",10,0f,0f),  new IndicatorDefaultScore("E.2.2",25,0f,0f),  new IndicatorDefaultScore("E.1.4",10,0f,0f),  new IndicatorDefaultScore("G.1.4",50,0f,0f),      new IndicatorDefaultScore("G.1.1",50,0f,0f),  new IndicatorDefaultScore("S.1.1",0,0f,0f),   new IndicatorDefaultScore("S.1.2",100,0f,0f) })
            };
        }
        private ReferenceUniverse GetSecondReferenceUniverse(Guid referenceUniverseId, IList<Guid> companyIds)
        {
            return
                   new ReferenceUniverse
                   {
                       Id = referenceUniverseId,
                       Companies = new[]
                    {
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704112",  CompanyId = companyIds[0], CompanyName = "Compania1" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704113",  CompanyId = companyIds[1], CompanyName = "Compania2" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704114",  CompanyId = companyIds[2], CompanyName = "Compania3" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704115",  CompanyId = companyIds[3], CompanyName = "Compania4" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704116",  CompanyId = companyIds[4], CompanyName = "Compania5" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704117",  CompanyId = companyIds[5], CompanyName = "Compania6" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ20704119",  CompanyId = companyIds[7], CompanyName = "Compania8" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ207041110", CompanyId = companyIds[8], CompanyName = "Compania9" },
                        new ReferenceUniverseCompany { CapitalIQID = "IQ207041111", CompanyId = companyIds[9], CompanyName = "Compania10" },
                    }
                   };
        }
    }
}